package ldh.im.dto.codec;

import ldh.im.ImCoder;
import ldh.im.dto.base.ErrorResp;
import ldh.im.dto.base.StatusResp;
import ldh.im.dto.base.SuccessResp;
import ldh.im.dto.business.*;
import ldh.im.dto.codec.binery.*;
import ldh.im.dto.codec.json.JsonCoder;
import ldh.im.dto.enmus.CodecType;
import ldh.im.dto.enmus.HandleType;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

public class CodecFactory {

//    private static final Logger LOGGER = LoggerFactory.getLogger(CodecFactory.class);

    private volatile static CodecFactory instance;
    private ConcurrentHashMap<String, Short> transferConcurrentHashMap;
    private ConcurrentHashMap<Short, TransferCode> transferConcurrentCodeHashMap;
    private ConcurrentHashMap<Short, HandleType> handleTypeConcurrentCodeHashMap;  // 分发器，本地处理还是异步处理

    private CodecFactory() {
        transferConcurrentHashMap = new ConcurrentHashMap<>();
        transferConcurrentCodeHashMap = new ConcurrentHashMap();
        handleTypeConcurrentCodeHashMap = new ConcurrentHashMap();
        initRegister();
    }

    public static CodecFactory getInstance() {
        if (instance == null) {
            synchronized (CodecFactory.class) {
                if (instance == null) {
                    instance = new CodecFactory();
                }
            }
        }
        return instance;
    }

    public TransferCode getTransfer(Class key, CodecType codecType) {
        String codeKey = key.getName() + "_" + codecType.getValue();
        Short codec = transferConcurrentHashMap.get(codeKey);
        if (codec == null) {
            throw new RuntimeException(String.format("没有%s对应的编码器", key.getName()));
        }
        return transferConcurrentCodeHashMap.get(codec);
    }

    public HandleType getHandleType(Short coder) {
        return handleTypeConcurrentCodeHashMap.get(coder);
    }

    public TransferCode getTransfer(Short code) {
        return transferConcurrentCodeHashMap.get(code);
    }

    // -2000 到 2000 属于内部编码器
    public void register(Class key, short code, ImCoder imCoder, HandleType handleType) {
        if (code < 2000 && code > - 2000) {
            throw new RuntimeException("code的值必须大于100");
        }
        register0(key, (int)code, imCoder, false, handleType);
    }

    private void register0(Class key, Integer code, ImCoder imCoder, boolean addJson, HandleType handleType) {
        String clazzKey = key.getName() + "_" + CodecType.binary.getValue();
        short shortCode = code.shortValue();
        TransferCode transferCode = new TransferCode(imCoder, shortCode);
        if (transferConcurrentHashMap.containsKey(clazzKey)) {
            throw new RuntimeException(String.format("%s已经存在", key.getName()));
        }
        if (transferConcurrentCodeHashMap.containsKey(shortCode)) {
            throw new RuntimeException(String.format("%s已经存在", shortCode));
        }
        transferConcurrentHashMap.putIfAbsent(clazzKey, shortCode);
        transferConcurrentCodeHashMap.putIfAbsent(shortCode, transferCode);
        handleTypeConcurrentCodeHashMap.putIfAbsent(shortCode, handleType);

        if (addJson) {
            Integer jsonShortCode = shortCode + 1000;
            clazzKey = key.getName() + "_" + CodecType.json.getValue();
            if (addJson && transferConcurrentCodeHashMap.containsKey(jsonShortCode)) {
                throw new RuntimeException(String.format("%s已经存在", jsonShortCode));
            }
            transferConcurrentHashMap.putIfAbsent(clazzKey, jsonShortCode.shortValue());
            transferConcurrentCodeHashMap.putIfAbsent(jsonShortCode.shortValue(), new TransferCode(new JsonCoder(key), jsonShortCode.shortValue()));
            handleTypeConcurrentCodeHashMap.putIfAbsent(jsonShortCode.shortValue(), handleType);
        }
    }

    /**
     * 注册统一编码器
     */
    private void initRegister() {
        register0(LoginReq.class, 1, new LoginCodec(), true, HandleType.local);  // 登录
        register0(LoginResp.class, 2, new LoginRecCodec(), true, HandleType.none);  // 登录返回
        register0(ErrorResp.class, 3, new ErrorRecCodec(), true, HandleType.none);  // 服务器返回的失败信息
        register0(ExitReq.class, 4, new ExitCodec(), true, HandleType.local);  // 退出
        register0(SuccessResp.class, 5, new SuccessResultCodec(), true, HandleType.none);  //  成功回执
        register0(StatusResp.class, 6, new StatusResultCodec(), true, HandleType.none);    // 状态回执
        register0(TransferFile.class, 7, new TransferFileCoder(), false, HandleType.local);
        register0(ReConnection.class, 8, new ReConnectionCodec(), true, HandleType.local);      // 重连（不需要再次登录）
        register0(ExitResp.class, 9, new SuccessResultCodec(), true, HandleType.local);  // 退出
        register0(ServerRedirectMessage.class, 10, new ServerRedirectMessageCodec(), true, HandleType.none);  // 服务器发送消息

        register0(P2pTextMessage.class, 11, new P2pTextMessageCodec(), true, HandleType.local);      // 文本信息
        register0(P2psTextMessage.class, 12, new P2psTextMessageCodec(), true, HandleType.local);      // 文本信息
        register0(P2gTextMessage.class, 13, new P2gTextMessageCodec(), true, HandleType.local);      // 文本信息
    }

}
